package org.dromara.tearoom.service.impl;



import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;

import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.dromara.tearoom.domain.vo.WxPayVo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.*;

/**
 * @description: 支付相关通用服务
 */
@RequiredArgsConstructor
@Service
public class PayService {
    @Value("${wechat.ip}")
    private  String ip;

    private final WxPayService wxPayService;

    /**
     * 根据传入的tradeType来进行不同类型的支付
     * @param dto 商品参数
     * @param tradeType WxPayConstants.TradeType.MWEB为H5支付/WxPayConstants.TradeType.NATIVE为扫码支付/WxPayConstants.TradeType.JSAPI为JSAPI支付
     * @return
     */
    public Object transactions(WxPayVo dto, String tradeType) {
        try {
            if (tradeType != null && !tradeType.isEmpty()){
                if (WxPayConstants.TradeType.MWEB.equals(tradeType)){
                    //H5支付
                    return noMiniappPay(dto, tradeType);
                }else if (WxPayConstants.TradeType.NATIVE.equals(tradeType)){
                    //NATIVE支付
                    return noMiniappPay(dto, tradeType);
                }else if (WxPayConstants.TradeType.JSAPI.equals(tradeType)){
                    //JSAPI支付
                    return payV3Order(dto);
                }
            }
        } catch (Exception e) {
            // 处理异常
            e.printStackTrace();
            return null;
        }
        return null;
    }

    private String noMiniappPay(WxPayVo dto, String tradeType) throws WxPayException {
        //设置请求参数
        WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
        request.setOutTradeNo(dto.getOutTradeNo());
        request.setTotalFee(dto.getTotalFee());
        request.setBody(dto.getBody());
        HttpServletRequest httpServletRequest = getHttpServletRequest();
        request.setSpbillCreateIp(httpServletRequest.getRemoteAddr());
        request.setNotifyUrl(dto.getNotifyUrl());
        request.setProductId(dto.getOutTradeNo());
        //设置下单方式
        request.setTradeType(tradeType);
        // 调用统一下单接口
        WxPayNativeOrderResult result = wxPayService.createOrder(request);
        // Native支付返回的二维码/H5支付返回的跳转链接
        String codeUrl = result.getCodeUrl();
        // 返回codeUrl给前端
        return codeUrl;
    }

    /**
     *
     * @param dto
     * @return
     */
//    public Map<String, String> miniappPay(WxPayVo dto) throws WxPayException {
//        // 使用V3专用请求对象
//        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
//        request.setDescription(dto.getBody());
//        request.setOutTradeNo(dto.getOutTradeNo());
//        request.setNotifyUrl(dto.getNotifyUrl());
//        request.setTimeExpire(dto.getTimeExpire());
//        // 金额设置
//        WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
//        amount.setTotal(dto.getTotalFee());
//        amount.setCurrency("CNY");
//        request.setAmount(amount);
//
//        // 支付者信息
//        WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
//        payer.setOpenid(dto.getOpenId());
//        request.setPayer(payer);
//
//        // 调用V3接口
//        WxPayUnifiedOrderV3Result.JsapiResult result =wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request);
//
//        return buildJsapiParams(dto);
//    }
    public  Object  payV3Order(WxPayVo dto){
       Map<String,Object> result  =null;
        try {
            WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
            WxPayUnifiedOrderV3Request.Payer payer = new WxPayUnifiedOrderV3Request.Payer();
            payer.setOpenid(dto.getOpenId());
            WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
            amount.setTotal(dto.getTotalFee());
            amount.setCurrency("CNY");
            request.setDescription(dto.getBody());
            request.setOutTradeNo(dto.getOutTradeNo());
            Date nowDate = new Date();
            Date dateAfter = new Date(nowDate.getTime() + 300000);
            String format = DateUtil.format(dateAfter, "yyyy-MM-dd'T'HH:mm:ssXXX");
            request.setTimeExpire(format);
            request.setNotifyUrl(dto.getNotifyUrl());
            request.setAmount(amount);
            request.setPayer(payer);
            WxPayUnifiedOrderV3Result.JsapiResult  signParam  =wxPayService.createOrderV3(TradeTypeEnum.JSAPI, request);
            result =new HashMap<>();
            result.put("paySign",signParam.getPaySign());
            result.put("package",signParam.getPackageValue());
            result.put("appId",signParam.getAppId());
            result.put("nonceStr",signParam.getNonceStr());
            result.put("timeStamp",signParam.getTimeStamp());
            result.put("signType",signParam.getSignType());
        } catch (Exception e) {
            System.out.println("微信支付失败！订单号：{} " + dto.getOutTradeNo() + ",原因:{}" + e.getMessage());
            e.getStackTrace();
        }
        return result;
    }
    /**
     * 获取到JS支付相关配置
     *
     * @param weiXinPayOrder
     * @return
     */
//    private Map<String, String> getWxJsapiPayParam(WxPayUnifiedOrderV3Result weiXinPayOrder) {
//        //WxPayParam中属性package1，签名使用key是package
//        String package_ = "prepay_id=" + weiXinPayOrder.getPrepayId();
//        Map<String, String> signParam = new LinkedHashMap<String, String>();
//        signParam.put("appId", weiXinPayOrder.getAppid());
//        signParam.put("nonceStr", UUID.randomUUID().toString().replace("-", ""));
//        signParam.put("package", package_);
//        signParam.put("signType", WxPayConstants.SignType.MD5);
//        signParam.put("timeStamp", System.currentTimeMillis() / 1000 + "");
//        String paySign = SignUtils.createSign(signParam,"SHA256-RSA", this.wxPayService.getConfig().getMchKey(), new String[0]);
//        signParam.put("paySign", paySign);
//        return signParam;
//    }
    /**
     * 微信退款
     * @param body
     * @return
     */
    public void wxRefund(WxPayVo  body) {
        WxPayRefundRequest refundRequest = new WxPayRefundRequest();
        refundRequest.setOutTradeNo(body.getOutTradeNo());
        refundRequest.setOutRefundNo(body.getOutRefundNo());
        refundRequest.setTotalFee(body.getTotalFee());
        refundRequest.setRefundFee(body.getTotalFee());
        refundRequest.setRefundDesc("商品退款");
        refundRequest.setNotifyUrl(body.getNotifyUrl());

        try {
            WxPayRefundResult result = wxPayService.refund(refundRequest);
            if (!"SUCCESS".equals(result.getResultCode())) {
                // 业务错误码和描述（如余额不足、订单已退款）
                String errCode = result.getErrCode();
                String errMsg = result.getErrCodeDes();
                throw new RuntimeException("退款失败: " + errCode + " - " + errMsg);
            }
            System.out.println("微信退款成功,返回参数{}" + JSONObject.toJSONString(result));
        } catch (WxPayException e) {
            throw new RuntimeException("退款失败: "+JSONObject.toJSONString(e));
        }
    }


    /**
     * 获取请求对象
     *
     * @return
     */
    private HttpServletRequest getHttpServletRequest() {
        HttpServletRequest request =  ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            System.out.println("请求头：" + key + "值：" + request.getHeader(key));
        }
        return request;
    }



}
